#region The MIT License
// The MIT License
// 
// Copyright (c) 2009 octalforty studios
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#endregion
using System;
using System.IO;
using System.Reflection;
using NUnit.Framework;
using octalforty.Componento.ComponentModel.Installation;
using octalforty.Componento.ComponentModel.Installation.FileSystem;
using octalforty.Componento.ComponentModel.Tracing;
using octalforty.Componento.Shared.SemanticModel;

namespace octalforty.Componento.Tests.Componento.ComponentModel.Installation
{
    [TestFixture()]
    public class InstalledComponentRegistryServiceTestFixture
    {
        #region Private Fields
        private InstalledComponentRegistryService installedComponentRegistry;
        #endregion

        [SetUp()]
        public void SetUp()
        {
            installedComponentRegistry = new InstalledComponentRegistryService(new TraceManagerService());
            installedComponentRegistry.DatabaseRootDirectory = 
                Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            installedComponentRegistry.FileSystemManager = new FileSystemManagerService();

            string databasePath = Path.Combine(installedComponentRegistry.DatabaseRootDirectory, "componento.db");
            if(File.Exists(databasePath))
                File.Delete(databasePath);

            installedComponentRegistry.OnImportsSatisfied();
        }

        [Test()]
        public void InstalledComponentsReturnsEmptyArrayWhenNoComponentsRegistered()
        {
            Assert.IsEmpty(installedComponentRegistry.InstalledComponents);
        }

        [Test()]
        public void RegisterComponent()
        {
            installedComponentRegistry.RegisterComponent(
                new ComponentReference("nunit", new Version(1, 2, 3, 4), new Uri("http://foo")));

            Assert.AreEqual(1, installedComponentRegistry.InstalledComponents.Length);
            Assert.AreEqual("nunit", installedComponentRegistry.InstalledComponents[0].Name);
            Assert.AreEqual(new Version(1, 2, 3, 4), installedComponentRegistry.InstalledComponents[0].Version);
            Assert.AreEqual(new Uri("http://foo"), installedComponentRegistry.InstalledComponents[0].Uri);
        }

        [Test()]
        public void RegisterComponentWithMajorVersionOnly()
        {
            installedComponentRegistry.RegisterComponent(
                new ComponentReference("nunit", new Version(1, 0), new Uri("http://foo")));

            Assert.AreEqual(1, installedComponentRegistry.InstalledComponents.Length);
            Assert.AreEqual("nunit", installedComponentRegistry.InstalledComponents[0].Name);
            Assert.AreEqual(new Version(1, 0), installedComponentRegistry.InstalledComponents[0].Version);
            Assert.AreEqual(new Uri("http://foo"), installedComponentRegistry.InstalledComponents[0].Uri);
        }

        [Test()]
        public void RegisterComponentWithMinorVersionOnly()
        {
            installedComponentRegistry.RegisterComponent(
                new ComponentReference("nunit", new Version(0, 1), new Uri("http://foo")));

            Assert.AreEqual(1, installedComponentRegistry.InstalledComponents.Length);
            Assert.AreEqual("nunit", installedComponentRegistry.InstalledComponents[0].Name);
            Assert.AreEqual(new Version(0, 1), installedComponentRegistry.InstalledComponents[0].Version);
            Assert.AreEqual(new Uri("http://foo"), installedComponentRegistry.InstalledComponents[0].Uri);
        }

        [Test()]
        public void UnregisterComponent()
        {
            installedComponentRegistry.RegisterComponent(
                new ComponentReference("nunit", new Version(1, 2, 3, 4), new Uri("http://foo")));
            installedComponentRegistry.RegisterComponent(
                new ComponentReference("nhibernate", new Version(4, 3, 2, 1), new Uri("http://foo/bar")));

            Assert.AreEqual(2, installedComponentRegistry.InstalledComponents.Length);

            installedComponentRegistry.UnregisterComponent("nhibernate");

            Assert.AreEqual(1, installedComponentRegistry.InstalledComponents.Length);
        }

        [Test()]
        [ExpectedException(typeof(ComponentRegistrationException))]
        public void RegisterComponentDoesNotAllowComponentsWithSameName()
        {
            installedComponentRegistry.RegisterComponent(
                new ComponentReference("nunit", new Version(1, 2, 3, 4), new Uri("http://foo/nunit")));
            installedComponentRegistry.RegisterComponent(
                new ComponentReference("nunit", new Version(1, 2, 3, 4), new Uri("http://foo/nhibernate")));
        }

        [Test()]
        public void RegisterComponentDependenciesAndGetComponentDependenciesAndDependants()
        {
            installedComponentRegistry.RegisterComponent(
                new ComponentReference("nunit", new Version(1, 2, 3, 4), new Uri("http://foo")));
            installedComponentRegistry.RegisterComponent(
                new ComponentReference("nhibernate", new Version(1, 2, 3, 4), new Uri("http://foo/bar")));
            installedComponentRegistry.RegisterComponent(
                new ComponentReference("nhibernate-linfu", new Version(1, 2, 3, 4), new Uri("http://foo/bar/baz")));

            installedComponentRegistry.RegisterComponentDependencies("nhibernate", new string[] { "nunit" });
            installedComponentRegistry.RegisterComponentDependencies("nhibernate-linfu", new string[] { "nhibernate" });
            installedComponentRegistry.RegisterComponentDependencies("nhibernate-linfu", new string[] { "nunit" });

            string[] dependencies = installedComponentRegistry.GetComponentDependencies("nhibernate");

            Assert.AreEqual(1, dependencies.Length);
            Assert.AreEqual("nunit", dependencies[0]);

            dependencies = installedComponentRegistry.GetComponentDependencies("nunit");

            Assert.IsNotNull(dependencies);
            Assert.IsEmpty(dependencies);

            string[] dependants = installedComponentRegistry.GetComponentDependants("nunit");

            Assert.AreEqual(2, dependants.Length);

            Assert.AreEqual("nhibernate", dependants[0]);
            Assert.AreEqual("nhibernate-linfu", dependants[1]);

            dependants = installedComponentRegistry.GetComponentDependants("nhibernate-linfu");

            Assert.IsNotNull(dependants);
            Assert.IsEmpty(dependants);
        }

        [Test()]
        public void GetComponentReferenceReturnsNullWhenNoComponentsRegistered()
        {
            Assert.IsNull(installedComponentRegistry.GetComponentReference("nhibernate"));
        }

        [Test()]
        public void GetComponentReference()
        {
            installedComponentRegistry.RegisterComponent(
                new ComponentReference("nhibernate", new Version(4, 3, 2, 1), new Uri("http://foo/bar")));

            ComponentReference componentReference = installedComponentRegistry.GetComponentReference("nhibernate");

            Assert.AreEqual(
                new ComponentReference("nhibernate", new Version(4, 3, 2, 1), new Uri("http://foo/bar")),
                componentReference);
        }

        [Test()]
        public void GetComponentDependenciesReturnsEmptyArrayWhenNoDependencies()
        {
            Assert.IsEmpty(installedComponentRegistry.GetComponentDependencies("nunit"));
        }

        [Test()]
        public void GetComponentDependantsReturnsEmptyArrayWhenNoDependencies()
        {
            Assert.IsEmpty(installedComponentRegistry.GetComponentDependants("nunit"));
        }
    }
}
